#include "xformat.h"
extern "C" {
#include "libavformat/avformat.h"
}
using namespace std;

bool XFormat::CopyPara(int stream_index, AVCodecParameters *dst) {
  std::unique_lock<std::mutex> lock(mux_);
  if (!c_)
    return false;
  if (stream_index < 0 || stream_index >= c_->nb_streams) {
    return false;
  }
  int ret = avcodec_parameters_copy(dst, c_->streams[stream_index]->codecpar);
  if (ret < 0) {
    return false;
  }
  return true;
}

bool XFormat::CopyPara(int stream_index, AVCodecContext *dst)
{
    std::unique_lock<std::mutex> lock(mux_);
  if (!c_)
    return false;
  if (stream_index < 0 || stream_index >= c_->nb_streams) {
    return false;
  }
  int ret = avcodec_parameters_to_context(dst, c_->streams[stream_index]->codecpar);
  if (ret < 0) {
    return false;
  }
  return true;
}

void XFormat::set_c(AVFormatContext *c) {
  unique_lock<std::mutex> lock(mux_);
  if (c_) {            // 清理原值
    if (c_->oformat) { // 输出上下文
      if (c_->pb)
        avio_close(c_->pb);
      avformat_free_context(c_);
    } else if (c_->iformat) {
      avformat_close_input(&c_);
    } else {
      avformat_free_context(c_);
    }
    c_ = nullptr;
  }
  c_ = c;
  if (!c_)
    return;
  audio_index_ = -1; // 用于区分是否有音频和视频流
  video_index_ = -1;
  // 区分音视频索引
  for (int i = 0; i < c_->nb_streams; ++i) {
    if (c_->streams[i]->codecpar->codec_type ==
        AVMediaType::AVMEDIA_TYPE_AUDIO) {
      audio_index_ = i;
      audio_time_base_.den = c_->streams[i]->time_base.den;
      audio_time_base_.num = c_->streams[i]->time_base.num;
      audio_codec_id_ = c_->streams[i]->codecpar->codec_id;
    } else if (c_->streams[i]->codecpar->codec_type ==
               AVMediaType::AVMEDIA_TYPE_VIDEO) {
      video_index_ = i;
      video_time_base_.den = c_->streams[i]->time_base.den;
      video_time_base_.num = c_->streams[i]->time_base.num;
      video_codec_id_ = c_->streams[i]->codecpar->codec_id;
    }
  }
}

bool XFormat::RescaleTime(AVPacket *pkt, long long offset_pts,
                          XRational time_base) {
  unique_lock<std::mutex> lock(mux_);
  if (!c_)
    return false;
  auto out_stream = c_->streams[pkt->stream_index];
  AVRational in_time_base = {time_base.num, time_base.den};
  // 因为截取了，所以pts应该减去前面10秒,再调用av_rescale_q_rnd来确保a*bq/cq
  pkt->pts = av_rescale_q_rnd(pkt->pts - offset_pts, in_time_base,
                              out_stream->time_base,
                              AVRounding(AV_ROUND_INF | AV_ROUND_PASS_MINMAX));
  pkt->dts = av_rescale_q_rnd(pkt->dts - offset_pts, in_time_base,
                              out_stream->time_base,
                              AVRounding(AV_ROUND_INF | AV_ROUND_PASS_MINMAX));
  pkt->duration =
      av_rescale_q(pkt->duration, in_time_base, out_stream->time_base);
  pkt->pos = -1;
  return true;
}